package com.ruoyi.app.service.impl;

import com.ruoyi.app.utils.AjaxResult;
import com.ruoyi.app.service.IAppUserLoginService;
import com.ruoyi.app.utils.AppUserUtils;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.AppUserStatus;
import com.ruoyi.common.request.AppRowData;
import com.ruoyi.common.request.Authcode2Session;
import com.ruoyi.common.security.AESForWeixinGetPhoneNumber;
import com.ruoyi.common.security.WeixinPhoneDecryptInfo;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.web.wuliu.domain.AppUser;
import com.ruoyi.web.wuliu.mapper.AppUserMapper;
import com.ruoyi.web.wuliu.service.IAppUserService;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Slf4j
@Service
public class AppUserLoginService implements IAppUserLoginService {

    public static final String APP_ID = "wx39f46b8cec4d8d94";
    public static final String APP_SECRET = "6c4bc0a56bc19f12821ffe96f7e789d5";

//    @Value("${order.appId}")
//    private String APP_ID;
//
//    @Value("${order.appSecret}")
//    private String APP_SECRET;

    @Autowired
    private IAppUserService userService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private TokenService tokenService;

    @Resource
    private AppUserMapper userMapper;

    /**
     * 调用微信认证
     *
     * @param code
     * @return
     */
    private Authcode2Session authFromWeixin(String code) {
        String appId = APP_ID;
        String appSecret = APP_SECRET;

        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId +
                "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
        Authcode2Session authResultFromWeixin = null;
        final int tryTimes = 3;
        for (int i = 0; i < tryTimes; i++) {
            String resultStr = restTemplate.getForObject(url, String.class);
            JSONObject jsonobject = JSONObject.fromObject(resultStr);
            authResultFromWeixin = (Authcode2Session) JSONObject.toBean(jsonobject, Authcode2Session.class);
            if (0 == authResultFromWeixin.getErrcode()) {
                break;
            }
        }
        return authResultFromWeixin;
    }

    private AppUser createUserByAppRowData(String openid, AppRowData appRowData, String mobilePhone) {
        AppUser user = new AppUser();
        user.setName(appRowData.getNickName());
        user.setOpenid(openid);
        user.setAvatarUrl(appRowData.getAvatarUrl());
//        user.setUsername(mobilePhone);
//        user.setAvatarUrl(appRowData.getAvatarUrl());
        user.setTelephone(mobilePhone);
        return user;
    }

    @Override
    @Transactional
    public AjaxResult<AppUser> appLogin(String code, String rawData, String encryptedData, String iv) {

//        try {
//            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
//
//            WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(sessionInfo.getSessionKey(), encryptedData, iv);
//            phoneNoInfo.getPurePhoneNumber();
//        } catch (WxErrorException e) {
//            e.printStackTrace();
//        }


        //微信认证
        Authcode2Session authResultFromWeixin = this.authFromWeixin(code);
        if (null == authResultFromWeixin || authResultFromWeixin.getErrcode() != 0) {
            log.error("微信认证失败！！！");
            log.info(authResultFromWeixin.toString());
            return AjaxResult.error("微信认证失败！！");
        }
        //请求成功
        String openid = authResultFromWeixin.getOpenid();
        log.info("微信认证成功后返回的数据：{}", authResultFromWeixin.toString());
        JSONObject rawDataJson = JSONObject.fromObject(rawData);
        AppRowData appRowData = (AppRowData) JSONObject.toBean(rawDataJson, AppRowData.class);
        //解密手机号
        AESForWeixinGetPhoneNumber aes = new AESForWeixinGetPhoneNumber(encryptedData, authResultFromWeixin.getSession_key(), iv);
        WeixinPhoneDecryptInfo phoneDecryptInfo = aes.decrypt();
        if (null == phoneDecryptInfo) {
            log.error("手机号解密失败！！！");
            return AjaxResult.error("手机号解密失败！！");
        }
        log.info("解密后的手机号信息：{}", phoneDecryptInfo.toString());
        //手机号查询用户
        AppUser user = userMapper.selectAppUserByOpid(openid);
        if (Objects.isNull(user)) {
            log.info("微信登录2：------------------>user为空");
            //说明用户第一次登录，数据库中创建用户
            String phoneNumber = phoneDecryptInfo.getPhoneNumber();
            log.info("微信登录3：------------------>phoneNumber为{}", phoneNumber);
            AppUser firstLoginUser = createUserByAppRowData(openid, appRowData, phoneNumber);
            firstLoginUser.setId(IdUtils.getUserId());
            firstLoginUser.setStatus(AppUserStatus.UNDERREVIEW.getCode());
            firstLoginUser.setStatus(AppUserStatus.UNDERREVIEW.getCode());
            try {
                userService.insertAppUser(firstLoginUser);
            } catch (UncategorizedSQLException e) {
                log.error(e.getMessage());
                return AjaxResult.error("您的昵称包含特殊字符，");
            }
            user = firstLoginUser;
        } else {
            //说明之前别人创建了此用户，或者非第一次登录，判断用户status，如果是冻结状态。则不允许登录
            if (Objects.equals(AppUserStatus.FROZEN.getCode(), user.getStatus())) {
                return AjaxResult.error("对不起，您的账号已经被冻结，不允许登录，请联系管理员!");
            }
            //更新该用户的信息
//            user.setAvatarUrl(appRowData.getAvatarUrl());
            user.setOpenid(openid);
            user.setUpdateTime(new Date());
            user.setName(appRowData.getNickName());
            try {
                userMapper.updateAppUser(user);
            } catch (UncategorizedSQLException e) {
                log.error(e.getMessage());
                return AjaxResult.error("您的昵称包含特殊字符，");
            }
        }
        // 生成token，并存入到redis和数据库中
        String token = getToken(user);
        log.info("生成的token为：{}", token);
        user.setToken(token);
        log.info("微信登录4：------------------>登录成功{}");
        return AjaxResult.success("用户登录成功", user);
    }

    @Override
    public AjaxResult<String> apploginOut(HttpServletRequest request) {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (Objects.nonNull(loginUser)) {
            tokenService.delLoginUser(loginUser.getToken());
        }
        return AjaxResult.success("退出成功");
    }

    @Override
    @Transactional
    public AjaxResult<AppUser> devLogin(String openid, String telephone) {
        AppRowData appRowData = new AppRowData();
        appRowData.setNickName("后台开发人员");
        //手机号查询用户
        AppUser user = userMapper.selectAppUserByTelephone(telephone);
        if (Objects.isNull(user)) {
            //说明用户第一次登录，数据库中创建用户
            AppUser firstLoginUser = createUserByAppRowData(openid, appRowData, telephone);
            firstLoginUser.setId(IdUtils.getUserId());
            firstLoginUser.setStatus(AppUserStatus.UNDERREVIEW.getCode());
            userService.insertAppUser(firstLoginUser);
            user = firstLoginUser;
        }
        // 生成token，并存入到redis和数据库中
        String token = getToken(user);
        log.info("生成的token为：{}", token);
        user.setToken(token);
        return AjaxResult.success("用户登录成功", user);
    }

    public String getToken(AppUser user) {
        LoginUser loginUser = new LoginUser(createManager(user), new HashSet<>());
        // 生成token
        return tokenService.createToken(loginUser);
    }

    private SysUser createManager(AppUser user) {
        SysUser sysUser = new SysUser();
        sysUser.setUserName(user.getName());
        sysUser.setUserId(Long.valueOf(user.getId()));
        sysUser.setRoles(new ArrayList<>());
        return sysUser;
    }

    @Override
    public AjaxResult<AppUser> getUser(HttpServletRequest request) {
        AppUser appUser = AppUserUtils.getAppUser();
        return AjaxResult.success(appUser);
    }
}
